/*
  数列分段 II
  题目描述
    对于给定的一个长度为 N 的正整数数列 A，现要将其分成 M 段，并要求每段连续，且每段和的最大值最小。
    例如，将数列 4  2  4  5  1 要分成 3 段：
      若分为 [4 2] [4 5] [1]，各段的和分别为 6,9,1，和的最大值为 9；
      若分为 [4] [2 4] [5 1]，各段的和分别为 4,6,6，和的最大值为 6；
      并且无论如何分段，最大值不会小于 6。
      所以可以得到要将数列 4  2  4  5  1 要分成 3 段，每段和的最大值最小为 6 。
  输入格式
    第 1 行包含两个正整数 N，M；
    第 2 行包含 N 个空格隔开的非负整数 Ai，含义如题目所述。
  输出格式
    仅包含一个正整数，即每段和最大值最小为多少。
  输入数据 1
    5 3
    4 2 4 5 1
  输出数据 1
    6
  数据范围：
    对于 20% 的数据，有 N ≤ 10；
    对于 40% 的数据，有 N ≤ 1000；
    对于 100% 的数据，有 N ≤ 10^5，M ≤ N，Ai 之和不超过 10^9。
*/

#include <bits/stdc++.h>

using namespace std;

/*
  思路:
    通常采用二分答案算法的话, 需要首先明确 2 个核心问题:
      1) 答案的取值范围(区间)，即确定区间的最大值和最小值
      2) 判断某个答案是否满足题意(条件)的判定方法
    解答本题时，先明确出这 2 个问题:
      1）答案的取值范围(区间)
          区间的最小值: 数列中的最大的数的值；
          区间的最大值: 数列中所有数的累加和；
      2) 判断某个答案是否满足题意的判定方法:
         首先依据答案计算出：该数列最少能划分成几个段中所有数的和小于等于答案的段；
         如果得到的段数大于 m，则说明该答案不满足条件；
         反之，则说明答案满足条件!
*/

int m, n;
int a[1000005]= {}; // a[i] 表示数列中的第 i 个数的值 (其中 i > 0)
int s = 1, e = 0;   // s(start) 表示二分答案算法实现中进行二分查找时的开始边界(左边界)
                    // e(end)   表示二分答案算法实现中进行二分查找时的结束边界(右边界)

// 该函数用来判断输入 x(表示答案，即每段中所有数之和的最大值) 是否满足条件(题目要求)
bool check(int x) {

    int sum = 0;
    int ans = 1;

    /*
      先依据答案计算出：该数列最少能划分成几个段中所有数的和小于等于答案的段
      计算方法: 从左向右查找数列中的每一个数，如果和前面的数的累加和大于答案，说明需要进行分段!
      如果得到的段数大于 m，则说明该答案不满足条件；
      反之，则说明答案满足条件!
    */
    for (int i = 1; i <= n; i++) {
        // 如果 sum + a[i] > x，则就分一段
        if (sum + a[i] > x) {
            ans++;
            sum = a[i];
        } else if (sum + a[i] == x) {
            sum += a[i];
        } else {
            sum += sum + a[i];
        }
    }

    return ans <= m;
}

int main() {
    cin >> n >> m; // 输入
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        e += a[i];
        if (s < a[i]) {
            s = a[i];
        }
    }

    /*
      用二分查找法，在答案的区间范围内，查找满足题目要求的最小值
    */
    int ans = INT_MAX;
    while (s <= e) {
        int mid = (s + e) / 2;
        if (check(mid)) {
            ans = mid;
            e = mid - 1;  // 由于需要答案尽可能地小，所以我们进一步从 mid 的左半区间进行查找
        } else {
            s = mid + 1;  // mid 不满足题目要求，从 mid 的右半区间进行查找
        }
    }
    cout << ans;

    return 0;
}